package com.hongyun.tms.web.controller;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.common.collect.Lists;
import com.hongyun.tms.common.PageResponseDto;
import com.hongyun.tms.common.annotation.excel.ExcelExport;
import com.hongyun.tms.common.constants.ProdPlanStatusConstant;
import com.hongyun.tms.common.dto.pordwork.*;
import com.hongyun.tms.common.dto.prodplan.ProPlanExportDto;
import com.hongyun.tms.common.dto.prodplan.ProPlanQueryDto;
import com.hongyun.tms.common.enums.DictTypeEnum;
import com.hongyun.tms.common.enums.ProdPlanEnum;
import com.hongyun.tms.common.enums.RateTradeTypeEnum;
import com.hongyun.tms.common.utils.DateUtils;
import com.hongyun.tms.common.utils.MapperingUtils;
import com.hongyun.tms.common.vo.PordWorkVO;
import com.hongyun.tms.domain.AjaxResult;
import com.hongyun.tms.entity.PordWork;
import com.hongyun.tms.entity.ProdPlan;
import com.hongyun.tms.infra.excel.StyleUtils;
import com.hongyun.tms.infra.excel.config.CustomCellWriteHeightConfig;
import com.hongyun.tms.infra.excel.config.CustomCellWriteWidthConfig;
import com.hongyun.tms.service.IPordWorkService;
import com.hongyun.tms.service.IProdPlanService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 拖轮作业记录表 前端控制器
 * </p>
 *
 * @author liPeng
 * @since 2024-06-14
 */
@Api(tags = "拖轮作业记录")
@RestController
@RequestMapping("/pordWork")
public class PordWorkController {
    @Resource
    private IPordWorkService workService;

    @Resource
    private IProdPlanService planService;

    /**
     * 分页查询
     *
     * @return page
     */
    @GetMapping("list")
    public AjaxResult<PageResponseDto<PordWorkVO>> list(PordWorkQueryDto query) {
        // 获取分页结果
        PageResponseDto<PordWorkVO> result = workService.pageList(query);

        // 提取所有记录中的 planId 并去重
        Set<Long> planIdSet = result.getRecords().stream()
                .map(PordWorkVO::getPlanId)
                .collect(Collectors.toSet());

        if (CollectionUtils.isNotEmpty(planIdSet)) {
            // 查询所有对应的 ProdPlan
            List<ProdPlan> planList = planService.list(new LambdaQueryWrapper<ProdPlan>().in(ProdPlan::getId, planIdSet));

            // 将 planList 转换为 Map，以 planId 为键，ProdPlan 为值
            Map<Long, ProdPlan> planMap = planList.stream()
                    .collect(Collectors.toMap(ProdPlan::getId, plan -> plan));

            // 遍历每个记录，将对应的 voyage 信息设置进去
            result.getRecords().forEach(record -> {
                ProdPlan plan = planMap.get(record.getPlanId());
                if (plan != null) {
                    record.setVoyage(plan.getVoyage());
                    record.setPlanCode(plan.getPlanCode());
                }
            });
        }
        return AjaxResult.success(result);
    }

    @ApiOperation("特殊作业记录")
    @GetMapping("specialList")
    public AjaxResult<PageResponseDto<PordWorkVO>> specialList(PordWorkSpecialQueryDto query) {
        PageResponseDto<PordWorkVO> result = workService.pageSpecialList(query);
        return AjaxResult.success(result);
    }
    @ApiOperation("特殊作业记录-总数据计费")
    @GetMapping("specialListTotalAmount")
    public AjaxResult<String> specialListTotalAmount(PordWorkSpecialQueryDto query) {
        String specialAmount =  workService.specialListTotalAmount(query);
        return AjaxResult.success(specialAmount);
    }


    /**
     * 根据ID查询
     *
     * @return PordWorkVO
     */
    @GetMapping("getById")
    public AjaxResult<PordWorkVO> getById(@RequestParam("id") Long id) {
        PordWorkVO vo = workService.detail(id);

        return AjaxResult.success(vo);
    }

    @PostMapping("save")
    @ApiOperation("新增/修改拖轮作业记录")
    public AjaxResult save(@RequestBody @Valid PordWorkSaveReqDto dto) {
        workService.saveOrUpdatePordWork(dto);
        return AjaxResult.success();
    }

    @PostMapping("modifyFinishWork")
    @ApiOperation("手动完工作业记录，参数：作业计划idList")
    public AjaxResult modifyFinishWork(@RequestBody @Valid List<String> idList) {

        List<PordWork> allWorkList = workService.list(new LambdaQueryWrapper<PordWork>().in(PordWork::getPlanId, idList));

        Map<Long, List<PordWork>> map = allWorkList.stream().collect(Collectors.groupingBy(PordWork::getPlanId));
        for (Long planId : map.keySet()) {
            List<PordWork> workList = map.get(planId);
            List<PordWork> emptyTimeList = workList.stream().filter((work) -> work.getBeginTime() == null).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(emptyTimeList)) {
                return AjaxResult.fail("计划" + planService.getById(planId).getPlanCode() + "存在作业时间为空的作业记录，无法完工");
            }
        }
        LambdaUpdateWrapper<ProdPlan> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(ProdPlan::getId, idList)
                .set(ProdPlan::getStatus, ProdPlanStatusConstant.FINISH_WORK);
        planService.update(updateWrapper);
        return AjaxResult.success();
    }

    @PostMapping("removeBatch")
    @ApiOperation("批量删除拖轮作业记录")
    public AjaxResult removeBatch(@RequestParam(name = "ids") String idList) {
        List<String> ids = Arrays.asList(idList.split(","));
        workService.removeByIds(ids);
        return AjaxResult.success();
    }

    @PostMapping("updateApproveBatch")
    @ApiOperation("作业记录批量审核")
    public AjaxResult updateApproveBatch(@RequestBody @Valid List<PordWorkBatchApproveReqDto> dtoList) {
        List<PordWork> copyList = MapperingUtils.copyList(dtoList, PordWork.class);
        workService.updateBatchById(copyList);
        return AjaxResult.success();
    }

    @SneakyThrows

    @GetMapping("exportWorkList")
    public void exportWorkList(ProPlanQueryDto queryDto, HttpServletResponse response) {
        // 文件信息
        String fileName = "作业记录导出";

        // 查询要导出的数据
        List<ProPlanExportDto> exportDtoList = planService.exportPlanList(queryDto);

        ExcelWriter excelWriter = null;
        WriteSheet writeSheet;

        try {
            // 设置response
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

            // 构建ExcelWriter
            excelWriter = EasyExcel.write(response.getOutputStream()).build();
            writeSheet = EasyExcel.writerSheet("sheet1").sheetNo(0).build();

            // 遍历 exportDtoList，生成表头和数据
            for (int i = 0; i < exportDtoList.size(); i++) {
                ProPlanExportDto plan = exportDtoList.get(i);

                // 一级表头（ProPlanExportDto 的字段）
                List<List<String>> planHeadList = new ArrayList<>();
                planHeadList.add(Lists.newArrayList("计划作业时间"));
                planHeadList.add(Lists.newArrayList("计划编号"));
                planHeadList.add(Lists.newArrayList("船名-航次"));
                planHeadList.add(Lists.newArrayList("泊位"));
                planHeadList.add(Lists.newArrayList("贸别"));
                planHeadList.add(Lists.newArrayList("进出"));
                planHeadList.add(Lists.newArrayList("装卸"));
                planHeadList.add(Lists.newArrayList("客户名称"));
                planHeadList.add(Lists.newArrayList("货名"));
                planHeadList.add(Lists.newArrayList("货重(吨)"));
                planHeadList.add(Lists.newArrayList("作业港区"));
                planHeadList.add(Lists.newArrayList("作业码头"));
                planHeadList.add(Lists.newArrayList("前吃水"));
                planHeadList.add(Lists.newArrayList("后吃水"));
                planHeadList.add(Lists.newArrayList("备注"));
                planHeadList.add(Lists.newArrayList("状态"));

                // 一级数据（ProPlanExportDto 的数据）
                List<List<String>> planData = new ArrayList<>();
                planData.add(Lists.newArrayList(
                        String.valueOf(plan.getPlanTime()),
                        plan.getPlanCode(),
                        plan.getShipName() + "-" + plan.getVoyage(),
                        plan.getBerthNo(),
                        Objects.requireNonNull(RateTradeTypeEnum.fromCode(plan.getTradeType())).getDesc(),
                        Objects.requireNonNull(ProdPlanEnum.fromCode(plan.getInOut())).getDesc(),
                        Objects.requireNonNull(ProdPlanEnum.fromCode(plan.getLoadUnload())).getDesc(),
                        plan.getCustomerName(),
                        plan.getCargoName(),
                        plan.getTon().toString(),
                        DictTypeEnum.PORT_AREA.getName(),
                        plan.getDockId() != null ? plan.getDockId().toString() : "",
                        plan.getFrontDraft() != null ? plan.getFrontDraft().toString() : "",
                        plan.getRearDraft() != null ? plan.getRearDraft().toString() : "",
                        plan.getRemark(),
                        plan.getStatus() != null ? Objects.requireNonNull(ProdPlanEnum.fromCode(plan.getStatus().toString())).getDesc() : ""
                ));

                WriteTable planTable = EasyExcel.writerTable(2 * i)
                        .head(planHeadList)
                        .registerWriteHandler(new HorizontalCellStyleStrategy(StyleUtils.getHeadStyle(), StyleUtils.getContentStyle()))
                        .registerWriteHandler(new CustomCellWriteHeightConfig())
                        .registerWriteHandler(new CustomCellWriteWidthConfig())
//                        .registerConverter(new ProdPlanEnumConverter())
//                        .registerConverter(new RateTradeTypeEnumConverter())
//                        .registerConverter(new DictConverter())
//                        .registerConverter(new LocalDateTimeOrDateConverter())
                        .build();
                excelWriter.write(planData, writeSheet, planTable);

                // 二级表头（PordWorkExportDto 的字段）
                List<List<String>> workHeadList = new ArrayList<>();
                workHeadList.add(Lists.newArrayList("拖轮编号"));
                workHeadList.add(Lists.newArrayList("作业项目"));
                workHeadList.add(Lists.newArrayList("开始作业时间"));
                workHeadList.add(Lists.newArrayList("结束作业时间"));
                workHeadList.add(Lists.newArrayList("作业时长(h)"));

                // 二级数据（PordWorkExportDto 的数据）
                List<List<String>> workData = new ArrayList<>();
                for (PordWorkExportDto work : plan.getChildren()) {
                    workData.add(Lists.newArrayList(work.getTugNo(),
                            work.getWorkItemName(),
                            DateUtils.localDateTime2Str(work.getBeginTime()),
                            DateUtils.localDateTime2Str(work.getEndTime()),
                            work.getWorkHours() == null ? "" : work.getWorkHours().toString()));
                }

                WriteTable workTable = EasyExcel.writerTable(2 * i + 1)
                        .head(workHeadList)
                        .registerWriteHandler(new HorizontalCellStyleStrategy(StyleUtils.getHeadStyle(), StyleUtils.getContentStyle()))
                        .registerWriteHandler(new CustomCellWriteHeightConfig())
                        .registerWriteHandler(new CustomCellWriteWidthConfig())
                        .build();
                excelWriter.write(workData, writeSheet, workTable);

                // 添加空行用于间隔
                List<List<String>> emptyRow = new ArrayList<>();
                emptyRow.add(Lists.newArrayList("", ""));
                excelWriter.write(emptyRow, writeSheet, workTable);
            }

        } finally {
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

    @GetMapping("exportSpecialList")
    @ExcelExport(value = SpecialWorkExportDto.class)
    public AjaxResult<List<SpecialWorkExportDto>> exportSpecialList(PordWorkSpecialQueryDto query, HttpServletResponse response) {
        List<SpecialWorkExportDto> exportList = (List<SpecialWorkExportDto>) workService.exportSpecialList(query, 1);
        return AjaxResult.success(exportList);
    }
    @GetMapping("exportSpecialFeeList")
    @ExcelExport(value = SpecialWorkFeeExportDto.class)
    public AjaxResult<List<SpecialWorkFeeExportDto>> exportSpecialFeeList(PordWorkSpecialQueryDto query, HttpServletResponse response) {
        List<SpecialWorkFeeExportDto> exportList = (List<SpecialWorkFeeExportDto>) workService.exportSpecialList(query, 2);
        return AjaxResult.success(exportList);
    }
}
